Komunikace programů zajišťují komponenty ServerSocket
(v serverovém programu) a ClientSocket
(v klientském programu). Tyto komponenty umožňují připojení několika klientů v jednomu serveru přes TCP/IP na libovolném portu. Já tyto komponenty používám k posílání stringů, což je pro tento účel dostačující.
Zprávy, které programy posílají mají tento tvar: prikaz1=par1;par2;par3;
Při testování jsem ale narazil na problém, že když pošlu více zpráv rychle za sebou, tak se mi spojí a přijdou jako jedna zpráva. Proto jsem musel ještě stanovit znak na oddělení zpráv. Zvolil jsem zpětné lomítko ("\").
Komunikace tedy probíhá tak, že na odesílající straně se naformuluje příkaz s parametrama a odešle se. Na přijímací straně se vyvolá událost, která spustí proceduru pro zpracování příchozí zprávy. Ta má rámcově tuto strukturu:
rozdělení na zprávy - celý příchozí string se rozdělí na jednotlivé stringy (každému stringu odopvídá jedna zpráva)
dekódování zprávy - celá zpráva se rozdělí na jednotlivé stringy (název příkazu a parametry)
provedení příkazu - provede se příkaz, který přišel ve zprávě. Když je více parametrů, tak se musí ještě provést dekódování parametrů (rozdělení na jednotlivé stringy).
Protože téměř všechny procedury a typy, které souvisí s komunikací, jsou stejné v serverovém i klientském programu, tak jsem pro tyto procedury a typy vytvořil další unitu ukom, která obsahuje:
PString - položka lineárního seznamu stringů
function Pridat(s:string;existPol:PString):PString;
- přidá string do lineárního seznamu stringů
Funkci Znicit
, která by zničila lineární seznam stringů, jsem nechal v jednotlivých programech, protože tam jsou deklarovány jako přetížené.
function RozdelNaZpravy(co:string):PString;
- rozdělí příchozí string na jednotlivé zpávy
procedure DekodujZpravu(zdroj:string; var typ,parametr:string);
- dekóduje zprávu (rodělení na název příkazu a parametry)
function DekodujRadek(const s:string):PString;
- dekóduje string, ve kterém jsou parametry (vytvoří stringy oddělené středníkem)
K ukládání začátku představení (TDateTime) jsem nejprve používal standartní funkce DateTimeToStr
a StrToDateTime
. Pak jsem ale zjistil, že převod do stringu je závislý na nastavení Windows a tak by se data uložená na jednom počídači nemusela správně dekódovat na jiném počítači. Proto jsem si tyto konverzní funkce udělal sám:
function StringDoCasu(s:string):TDateTime;
- převede string do TDateTime
function CasDoStringu(const c:TDateTime):string;
- převede TDateTime do stringu
Zprávy, které mohou přijít serveru (odesílá je klient):
login=username;heslo;\
- autorizace
buy=sal;NazevPredstaveni;zacatek;cena;X;Y;rada;sedadlo;0;\
- koupení vstupenky (poslední parametr označuje, zda se bude vstupenka tisknout)
unbuy=sal;NazevPredstaveni;zacatek;X;Y;\
- zrušení koupě
sal=nazev;\
- žádost, aby mu server poslal seznam konkrétních představení v tomto sále
salkp=sal;nazev;cas;\
- žádost, aby mu server poslal seznam obsazených sedadel na toto konkrétní představení
Zprávy, které mohou přijít klientovi (odesílá je server):
login=\
- aby klient poslal své přihlašovací jméno a heslo
odpojit=\
- aby se klient odpojil
badname=\
- špatné přihlašovací jméno
badpass=\
- špatné přihlašovací heslo
uzprip=\
- uživatel s takovým přihlašovacím jménem je již připojen
odpojit=\
- aby se klient odpojil
salkpall=sal;NazevPredstaveni1;Zacatek1;Cena1;NazevPredstaveni2;Zacatek2;Cena2;...;\
- seznam konkrétních představení v jednom sále
salneex=sal;sirka;vyska;x1;y1;x2;y2;...;\
- rozměry sálu a seznam neexistujících sedadel
salkp=sal;NazevPredstaveni;Zacatek;obsX1;obsY1;obsX2;obsY2;...;\
- seznam obsazených sedadel na konkrétní představení
saly=sal1;sal2;...;\
- seznam sálů
buyprint=sal;NazevPredstaveni;zacatek;cena;X;Y;rada;sedadlo;0;\
- vytištění koupené vstupenky